home *** CD-ROM | disk | FTP | other *** search
/ Experimental BBS Explossion 3 / Experimental BBS Explossion III.iso / games / nhak_src.zip / UHITM.C < prev    next >
C/C++ Source or Header  |  1993-03-16  |  41KB  |  1,506 lines

  1. /*    SCCS Id: @(#)uhitm.c    3.0    89/11/27
  2. /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
  3. /* NetHack may be freely redistributed.  See license for details. */
  4.  
  5. #include    "hack.h"
  6. #ifdef NAMED_ITEMS
  7. #  include "artifact.h"
  8. #endif
  9.  
  10. static boolean FDECL(known_hitum, (struct monst *,int));
  11. static boolean FDECL(hitum, (struct monst *,int));
  12. #ifdef POLYSELF
  13. static int FDECL(explum, (struct monst *,struct attack *));
  14. static int FDECL(gulpum, (struct monst *,struct attack *));
  15. static boolean FDECL(hmonas, (struct monst *,int));
  16. #endif
  17. static void FDECL(nohandglow, (struct monst *));
  18.  
  19. #ifdef WORM
  20. extern boolean notonhead;
  21. #endif
  22.  
  23. struct monst *
  24. clone_mon(mon)
  25. struct monst *mon;
  26. {
  27.     coord mm;
  28.     struct monst *m2;
  29.  
  30.     mm.x = mon->mx;
  31.     mm.y = mon->my;
  32.     if (!enexto(&mm, mm.x, mm.y, mon->data)) return (struct monst *)0;
  33.     if (MON_AT(mm.x, mm.y) || mon->mhp <= 1) return (struct monst *)0;
  34.     m2 = newmonst(0);
  35.     *m2 = *mon;            /* copy condition of old monster */
  36.     m2->nmon = fmon;
  37.     fmon = m2;
  38.     m2->m_id = flags.ident++;
  39.     m2->mx = mm.x;
  40.     m2->my = mm.y;
  41.  
  42.     m2->minvent = (struct obj *) 0; /* objects don't clone */
  43.     m2->mleashed = FALSE;
  44.     m2->mgold = 0L;
  45.     /* Max HP the same, but current HP halved for both.  The caller
  46.      * might want to override this by halving the max HP also.
  47.      */
  48.     m2->mhpmax = mon->mhpmax;
  49.     m2->mhp = mon->mhp /= 2;
  50.  
  51.     /* since shopkeepers and guards will only be cloned if they've been
  52.      * polymorphed away from their original forms, the clone doesn't have
  53.      * room for the extra information.  we also don't want two shopkeepers
  54.      * around for the same shop.
  55.      * similarly, clones of named monsters don't have room for the name,
  56.      * so we just make the clone unnamed instead of bothering to create
  57.      * a clone with room and copying over the name from the right place
  58.      * (which changes if the original was a shopkeeper or guard).
  59.      */
  60.     if (mon->isshk) m2->isshk = FALSE;
  61.     if (mon->isgd) m2->isgd = FALSE;
  62. #if defined(ALTARS) && defined(THEOLOGY)
  63.     if (mon->ispriest) m2->ispriest = FALSE;
  64. #endif
  65.     m2->mxlth = 0;
  66.     m2->mnamelth = 0;
  67.     m2->mdispl = 0;
  68.     pmon(m2);    /* display the new monster */
  69.     place_monster(m2, m2->mx, m2->my);
  70.     if (mon->mtame) {
  71.         struct monst *m3;
  72.  
  73.         if (m3 = tamedog(m2, (struct obj *)0))
  74.         m2 = m3;
  75.     }
  76.     return m2;
  77. }
  78.  
  79. boolean
  80. special_case(mtmp)
  81. /* Moved this code from attack() in order to     */
  82. /* avoid having to duplicate it in dokick.    */
  83. register struct monst *mtmp;
  84. {
  85.     if (flags.confirm && (mtmp->mpeaceful || mtmp->mtame) && !Confusion
  86.         && !Hallucination && (!mtmp->mhide || !mtmp->mundetected)
  87.         && (!mtmp->mimic || Protection_from_shape_changers)) {
  88.         if (Blind ? Telepat : (!mtmp->minvis || See_invisible)) {
  89. #ifdef MACOS
  90.             char mac_tbuf[80];
  91.             if(!flags.silent) SysBeep(1);
  92.             Sprintf(mac_tbuf, "Really attack %s?", mon_nam(mtmp));
  93.             if(UseMacAlertText(128, mac_tbuf) != 1) {
  94. #else
  95.             pline("Really attack %s? ", mon_nam(mtmp));
  96.             (void) fflush(stdout);
  97.             if (yn() != 'y') {
  98. #endif
  99.                 flags.move = 0;
  100.                 return(TRUE);
  101.             }
  102.         }
  103.     }
  104.  
  105.     if(mtmp->mimic && !Protection_from_shape_changers) {
  106.         stumble_onto_mimic(mtmp);
  107.         return(TRUE);
  108.     }
  109.  
  110.     if(mtmp->mhide && mtmp->mundetected && !canseemon(mtmp)) {
  111.         mtmp->mundetected = 0;
  112.         if (!(Blind ? Telepat : (HTelepat & WORN_HELMET))) {
  113.             register struct obj *obj;
  114.  
  115.             if(Blind) pline("Wait!  There's a hidden monster there!");
  116.             else if(OBJ_AT(mtmp->mx, mtmp->my)) {
  117.             if(obj = level.objects[mtmp->mx][mtmp->my])
  118.                 pline("Wait!  There's %s hiding under %s!",
  119.                     defmonnam(mtmp), doname(obj));
  120.             } else if (levl[mtmp->mx][mtmp->my].gmask == 1)
  121.                 pline("Wait!  There's %s hiding under some gold!",
  122.                     defmonnam(mtmp));
  123.             wakeup(mtmp);
  124.             return(TRUE);
  125.         }
  126.     }
  127.     return(FALSE);
  128. }
  129.  
  130. schar
  131. find_roll_to_hit(mtmp)
  132. register struct monst *mtmp;
  133. {
  134.     schar tmp;
  135.     struct permonst *mdat = mtmp->data;
  136.  
  137. #ifdef POLYSELF
  138.     tmp = Luck + mdat->ac + abon() +
  139.              ((u.umonnum >= 0) ? uasmon->mlevel : u.ulevel);
  140. #else
  141.     tmp = Luck + u.ulevel + mdat->ac + abon();
  142. #endif
  143. /*    it is unchivalrous to attack the defenseless or from behind */
  144.     if (pl_character[0] == 'K' && u.ualigntyp == U_LAWFUL &&
  145.         (!mtmp->mcanmove || mtmp->msleep || mtmp->mflee) &&
  146.         u.ualign > -10) adjalign(-1);
  147.  
  148. /*    Adjust vs. (and possibly modify) monster state.        */
  149.  
  150.     if(mtmp->mstun) tmp += 2;
  151.     if(mtmp->mflee) tmp += 2;
  152.  
  153.     if(mtmp->msleep) {
  154.         mtmp->msleep = 0;
  155.         tmp += 2;
  156.     }
  157.     if(!mtmp->mcanmove) {
  158.         tmp += 4;
  159.         if(!rn2(10)) {
  160.             mtmp->mcanmove = 1;
  161.             mtmp->mfrozen = 0;
  162.         }
  163.     }
  164.     if (is_orc(mtmp->data) && pl_character[0]=='E') tmp++;
  165.  
  166. /*    with a lot of luggage, your agility diminishes */
  167.     tmp -= (inv_weight() + 40)/20;
  168.     if(u.utrap) tmp -= 3;
  169. #ifdef POLYSELF
  170. /*    Some monsters have a combination of weapon attacks and non-weapon
  171.  *    attacks.  It is therefore wrong to add hitval to tmp; we must add it
  172.  *    only for the specific attack (in hmonas()).
  173.  */
  174.     if(uwep && u.umonnum == -1) tmp += hitval(uwep, mdat);
  175. #else
  176.     if(uwep) tmp += hitval(uwep, mdat);
  177. #endif
  178.     return tmp;
  179. }
  180.  
  181. /* try to attack; return FALSE if monster evaded */
  182. /* u.dx and u.dy must be set */
  183. boolean
  184. attack(mtmp)
  185. register struct monst *mtmp;
  186. {
  187.     schar tmp = 0;
  188.     register struct permonst *mdat = mtmp->data;
  189.  
  190.     if(unweapon) {
  191.         unweapon=FALSE;
  192.         if(flags.verbose)
  193.         if(uwep)
  194.             You("begin bashing monsters with your %s.",
  195.             aobjnam(uwep, NULL));
  196.         else
  197. #ifdef POLYSELF
  198.             if (!cantwield(uasmon))
  199. #endif
  200.             You("begin bashing monsters with your %s hands.",
  201.             uarmg ? "gloved" : "bare");        /* Del Lamb */
  202.     }
  203.     /* andrew@orca: prevent unlimited pick-axe attacks */
  204.     u_wipe_engr(3);
  205.  
  206.     if(mdat->mlet == S_LEPRECHAUN && mtmp->mfrozen && !mtmp->msleep &&
  207.        !mtmp->mconf && mtmp->mcansee && !rn2(7) &&
  208.        (m_move(mtmp, 0) == 2 ||                /* he died */
  209.        mtmp->mx != u.ux+u.dx || mtmp->my != u.uy+u.dy)) /* he moved */
  210.         return(FALSE);
  211.  
  212.     /* This section of code provides protection against accidentally
  213.      * hitting peaceful (like '@') and tame (like 'd') monsters.
  214.      * There is protection only if you're not blind, confused, or hallu-
  215.      * cinating.
  216.      */
  217.     /*  changes by wwp 5/16/85 */
  218.     if (!Confusion && !Hallucination && flags.safe_dog &&
  219.         (Blind ? Telepat : (!mtmp->minvis || See_invisible)) &&
  220.                                 mtmp->mtame) {
  221.         mtmp->mflee = 1;
  222.         mtmp->mfleetim = rnd(6);
  223.         if (mtmp->mnamelth)
  224.             You("stop to avoid hitting %s.", NAME(mtmp));
  225.         else
  226.             You("stop to avoid hitting your %s.",
  227.               mdat->mname);
  228.         return(TRUE);
  229.     }
  230.  
  231.     /* moved code to a separate function to share with dokick */
  232.     if(special_case(mtmp)) return(TRUE);
  233.  
  234. #ifdef POLYSELF
  235.     if(u.umonnum >= 0) {    /* certain "pacifist" monsters don't attack */
  236.         set_uasmon();
  237.         if(noattacks(uasmon)) {
  238.             You("have no way to attack monsters physically.");
  239.             return(TRUE);
  240.         }
  241.     }
  242. #endif
  243.  
  244.     tmp = find_roll_to_hit(mtmp);
  245. #ifdef POLYSELF
  246.     if (u.umonnum >= 0) (void) hmonas(mtmp, tmp);
  247.     else
  248. #endif
  249.         (void) hitum(mtmp, tmp);
  250.     return(TRUE);
  251. }
  252.  
  253. static boolean
  254. known_hitum(mon, mhit)    /* returns TRUE if monster still lives */
  255. /* Made into a separate function because in some cases we want to know
  256.  * in the calling function whether we hit.
  257.  */
  258. register struct monst *mon;
  259. register int mhit;
  260. {
  261.     register boolean malive = TRUE;
  262.  
  263.     stoned = FALSE;        /* this refers to the thing hit, not you */
  264.  
  265.     if(!mhit) {
  266.         if(!Blind && flags.verbose) You("miss %s.", mon_nam(mon));
  267.         else            You("miss it.");
  268.         if(!mon->msleep && mon->mcanmove)
  269.         wakeup(mon);
  270.     } else {
  271.         /* we hit the monster; be careful: it might die! */
  272.  
  273. #ifdef WORM
  274.         if (mon->mx != u.ux+u.dx || mon->my != u.uy+u.dy)
  275.         notonhead = TRUE;
  276. #endif
  277.         if((malive = hmon(mon, uwep, 0)) == TRUE) {
  278.         /* monster still alive */
  279.         if(!rn2(25) && mon->mhp < mon->mhpmax/2) {
  280.             mon->mflee = 1;
  281.             if(!rn2(3)) mon->mfleetim = rnd(100);
  282.             if(u.ustuck == mon && !u.uswallow
  283. #ifdef POLYSELF
  284.                         && !sticks(uasmon)
  285. #endif
  286.                                 )
  287.                 u.ustuck = 0;
  288.         }
  289. #ifdef WORM
  290.         if(mon->wormno)
  291.             cutworm(mon, u.ux+u.dx, u.uy+u.dy,
  292.                 uwep ? uwep->otyp : 0);
  293. #endif
  294.         }
  295. #if defined(ALTARS) && defined(THEOLOGY)
  296.         if(mon->ispriest && !rn2(2)) ghod_hitsu();
  297. #endif
  298.     }
  299.     return(malive);
  300. }
  301.  
  302. static boolean
  303. hitum(mon, tmp)        /* returns TRUE if monster still lives */
  304. struct monst *mon;
  305. int tmp;
  306. {
  307.     static int NEARDATA malive;
  308.     boolean mhit = (tmp > rnd(20) || u.uswallow);
  309.  
  310.     malive = known_hitum(mon, mhit);
  311.     (void) passive(mon, mhit, malive, FALSE);
  312.     return(malive);
  313. }
  314.  
  315. boolean            /* general "damage monster" routine */
  316. hmon(mon, obj, thrown)        /* return TRUE if mon still alive */
  317. register struct monst *mon;
  318. register struct obj *obj;
  319. register int thrown;
  320. {
  321.     register int tmp;
  322.     struct permonst *mdat = mon->data;
  323.     /* Why all these booleans?  This stuff has to be done in the
  324.      *      following order:
  325.      * 1) Know what we're attacking with, and print special hittxt for
  326.      *    unusual cases.
  327.      * 2a) Know whether we did damage (depends on 1)
  328.      * 2b) Know if it's poisoned (depends on 1)
  329.      * 2c) Know whether we get a normal damage bonus or not (depends on 1)
  330.      * 3a) Know what the value of the damage bonus is (depends on 2c)
  331.      * 3b) Know how much poison damage was taken (depends on 2b) and if the
  332.      *    poison instant-killed it
  333.      * 4) Know if it was killed (requires knowing 3a, 3b) except by instant-
  334.      *    kill poison
  335.      * 5) Print hit message (depends on 1 and 4)
  336.      * 6a) Print poison message (must be done after 5)
  337. #if 0
  338.      * 6b) Rust weapon (must be done after 5)
  339. #endif
  340.      * 7) Possibly kill monster (must be done after 6a, 6b)
  341.      * 8) Instant-kill from poison (can happen anywhere between 5 and 9)
  342.      * 9) Hands not glowing (must be done after 7 and 8)
  343.      * The major problem is that since we don't want a "hit" message
  344.      * when the monster dies, we have to know how much damage it did
  345.      * _before_ outputting a hit message, but any messages associated with
  346.      * the damage don't come out until _after_ outputting a hit message.
  347.      */
  348.     boolean hittxt = FALSE, destroyed = FALSE;
  349.     boolean get_dmg_bonus = TRUE;
  350.     boolean ispoisoned = FALSE, needpoismsg = FALSE, poiskilled = FALSE;
  351.     boolean silvermsg = FALSE;
  352.  
  353.     wakeup(mon);
  354.     if(!obj) {
  355.         tmp = rnd(2);    /* attack with bare hands */
  356. #if 0
  357.         if(mdat == &mons[PM_COCKATRICE] && !uarmg
  358. #ifdef POLYSELF
  359.         && !resists_ston(uasmon)
  360. #endif
  361.         ) {
  362.  
  363.         kludge("You hit %s with your bare %s.",
  364.             mon_nam(mon), makeplural(body_part(HAND)));
  365.         You("turn to stone...");
  366.         done_in_by(mon);
  367.         hittxt = TRUE; /* maybe lifesaved */
  368.         }
  369. #endif
  370.     } else {
  371.         if(obj->olet == WEAPON_SYM || obj->otyp == PICK_AXE ||
  372.            obj->otyp == UNICORN_HORN || obj->olet == ROCK_SYM) {
  373.  
  374.         if(obj == uwep && (obj->otyp >= BOW || obj->otyp < BOOMERANG)
  375.             && obj->otyp != PICK_AXE && obj->otyp != UNICORN_HORN)
  376.             tmp = rnd(2);
  377.         else {
  378.             tmp = dmgval(obj, mdat);
  379. #ifdef NAMED_ITEMS
  380.             if(spec_ability(obj, SPFX_DRLI) && !resists_drli(mdat)) {
  381.             if (!Blind) {
  382.                 pline("The %s blade draws the life from %s!",
  383.                 Hallucination ? hcolor() : black,
  384.                 mon_nam(mon));
  385.                 hittxt = TRUE;
  386.             }
  387.             if (mon->m_lev == 0) tmp = mon->mhp;
  388.             else {
  389.                 int drain = rnd(8);
  390.                 tmp += drain;
  391.                 mon->mhpmax -= drain;
  392.                 mon->m_lev--;
  393.             }
  394.             }
  395. #endif
  396.             if(!thrown && obj == uwep && obj->otyp == BOOMERANG &&
  397.                !rnl(3)) {
  398.             kludge("As you hit %s, the boomerang breaks into splinters.",
  399.                   mon_nam(mon));
  400.             useup(obj);
  401.             hittxt = TRUE;
  402.             tmp++;
  403.             }
  404.             if(thrown && (obj->otyp >= ARROW && obj->otyp <= SHURIKEN)){
  405.             if(((uwep && objects[obj->otyp].w_propellor ==
  406.                 -objects[uwep->otyp].w_propellor)
  407.                 || obj->otyp==DART || obj->otyp==SHURIKEN) &&
  408.                 obj->opoisoned)
  409.                 ispoisoned = TRUE;
  410.             }
  411.             if(thrown && obj->otyp == SILVER_ARROW) {
  412.             if (is_were(mdat) || mdat->mlet==S_VAMPIRE
  413.                 || (mdat->mlet==S_IMP && mdat != &mons[PM_TENGU])
  414.                 || is_demon(mdat)) {
  415.                 silvermsg = TRUE;
  416.                 tmp += rnd(20);
  417.             }
  418.             }
  419.         }
  420.         } else if(obj->olet == POTION_SYM) {
  421.             if (obj->quan > 1) setuwep(splitobj(obj, 1));
  422.             else setuwep((struct obj *)0);
  423.             freeinv(obj);
  424.             potionhit(mon,obj);
  425.             hittxt = TRUE;
  426.             tmp = 1;
  427.         } else    switch(obj->otyp) {
  428.         case HEAVY_IRON_BALL:
  429.             tmp = rnd(25); break;
  430.         case BOULDER:
  431.             tmp = rnd(20); break;
  432. #ifdef MEDUSA
  433.         case MIRROR:
  434.             You("break your mirror.  That's bad luck!");
  435.             change_luck(-2);
  436.             useup(obj);
  437.             hittxt = TRUE;
  438.             tmp = 1;
  439.             break;
  440. #endif
  441.         case EXPENSIVE_CAMERA:
  442.     You("succeed in destroying your camera.  Congratulations!");
  443.             useup(obj);
  444.             return(TRUE);
  445.         case CORPSE:        /* fixed by polder@cs.vu.nl */
  446.             if(obj->corpsenm == PM_COCKATRICE) {
  447.                 kludge("You hit %s with the cockatrice corpse.",
  448.                   mon_nam(mon));
  449.                 if(resists_ston(mdat)) {
  450.                 tmp = 1;
  451.                 hittxt = TRUE;
  452.                 break;
  453.                 }
  454.                 kludge("%s turns to stone.", Monnam(mon));
  455.                 stoned = TRUE;
  456.                 xkilled(mon,0);
  457.                 nohandglow(mon);
  458.                 return(FALSE);
  459.             }
  460.             tmp = mons[obj->corpsenm].msize + 1;
  461.             break;
  462.         case EGG: /* only possible if hand-to-hand */
  463.             if(obj->corpsenm > -1
  464.                     && obj->corpsenm != PM_COCKATRICE
  465.                     && mdat == &mons[PM_COCKATRICE]) {
  466.                 kludge("You hit %s with the %s egg%s.",
  467.                     mon_nam(mon),
  468.                     mons[obj->corpsenm].mname,
  469.                     plur((long)obj->quan));
  470.                 hittxt = TRUE;
  471.                 pline("The egg%sn't live any more...",
  472.                     (obj->quan==1) ? " is" : "s are");
  473.                 obj->otyp = ROCK;
  474.                 obj->olet = GEM_SYM;
  475.                 obj->known = obj->dknown = 0;
  476.                 obj->owt = weight(obj);
  477.             }
  478.             tmp = 1;
  479.             break;
  480.         case CLOVE_OF_GARLIC:        /* no effect against demons */
  481.             if(is_undead(mdat)) mon->mflee = 1;
  482.             tmp = 1;
  483.             break;
  484.         case CREAM_PIE:
  485. #ifdef POLYSELF
  486.         case BLINDING_VENOM:
  487.             if(Blind)
  488.                 pline(obj->otyp==CREAM_PIE ? "Splat!" : "Splash!");
  489.             else if (obj->otyp == BLINDING_VENOM)
  490.                 pline("The venom blinds %s%s!", mon_nam(mon),
  491.                     mon->mcansee ? "" : " further");
  492. #else
  493.             if(Blind) pline("Splat!");
  494. #endif
  495.             else
  496.                 pline("The cream pie splashes over %s%s!",
  497.                 mon_nam(mon),
  498.                 (haseyes(mdat) &&
  499.                     mdat != &mons[PM_FLOATING_EYE])
  500.                 ? "'s face" : "");
  501.             if(mon->msleep) mon->msleep = 0;
  502.             setmangry(mon);
  503.             mon->mcansee = 0;
  504.             tmp = rnd(25) + 20;
  505.             if((mon->mblinded + tmp) > 127) mon->mblinded = 127;
  506.             else mon->mblinded += tmp;
  507.             hittxt = TRUE;
  508.             get_dmg_bonus = FALSE;
  509.             tmp = 0;
  510.             break;
  511. #ifdef POLYSELF
  512.         case ACID_VENOM: /* only possible if thrown */
  513.             if(resists_acid(mdat)) {
  514.                 kludge("Your venom hits %s harmlessly.",
  515.                     mon_nam(mon));
  516.                 tmp = 0;
  517.             } else {
  518.                 kludge("Your venom burns %s!", mon_nam(mon));
  519.                 tmp = dmgval(obj, mdat);
  520.             }
  521.             hittxt = TRUE;
  522.             get_dmg_bonus = FALSE;
  523.             break;
  524. #endif
  525.         default:
  526.             /* non-weapons can damage because of their weight */
  527.             /* (but not too much) */
  528.             tmp = obj->owt/10;
  529.             if(tmp < 1) tmp = 1;
  530.             else tmp = rnd(tmp);
  531.             if(tmp > 6) tmp = 6;
  532.         }
  533.     }
  534.  
  535.     /****** NOTE: perhaps obj is undefined!! (if !thrown && BOOMERANG)
  536.      *      *OR* if attacking bare-handed!! */
  537.  
  538.     if (get_dmg_bonus) {
  539.         tmp += u.udaminc;
  540.         /* If you throw using a propellor, you don't get a strength
  541.          * bonus but you do get an increase-damage bonus.
  542.          */
  543.         if(!thrown || !obj || !uwep ||
  544.             (obj->olet != GEM_SYM && obj->olet != WEAPON_SYM) ||
  545.             !objects[obj->otyp].w_propellor ||
  546.             (objects[obj->otyp].w_propellor !=
  547.                 -objects[uwep->otyp].w_propellor))
  548.             tmp += dbon();
  549.     }
  550.  
  551. /* TODO:    Fix this up.  multiple engulf attacks now exist.
  552.     if(u.uswallow) {
  553.         if((tmp -= u.uswldtim) <= 0) {
  554.         Your("%s are no longer able to hit.",
  555.             makeplural(body_part(ARM)));
  556.         return(TRUE);
  557.         }
  558.     }
  559.  */
  560.     if (ispoisoned) {
  561.         if(resists_poison(mdat))
  562.         needpoismsg = TRUE;
  563.         else if (rn2(10))
  564.         tmp += rnd(6);
  565.         else poiskilled = TRUE;
  566.     }
  567.     if(tmp < 1) tmp = 1;
  568.  
  569.     mon->mhp -= tmp;
  570.     if(mon->mhp < 1)
  571.         destroyed = TRUE;
  572.     if(mon->mtame && (!mon->mflee || mon->mfleetim)) {
  573. #ifdef SOUNDS
  574.         if (rn2(8)) yelp(mon);
  575.         else growl(mon); /* give them a moment's worry */
  576. #endif
  577.         mon->mtame--;
  578.         mon->mflee = 1;            /* Rick Richardson */
  579.         mon->mfleetim += 10*rnd(tmp);
  580.     }
  581.     if((mdat == &mons[PM_BLACK_PUDDING] || mdat == &mons[PM_BROWN_PUDDING])
  582.            && obj && obj == uwep
  583.            && objects[obj->otyp].oc_material == METAL
  584.            && mon->mhp > 1 && !thrown && !mon->mcan
  585.            /* && !destroyed  -- guaranteed by mhp > 1 */ ) {
  586.  
  587.         if (clone_mon(mon)) {
  588.             kludge("%s divides as you hit it!", Monnam(mon));
  589.             hittxt = TRUE;
  590.         }
  591.     }
  592.  
  593.     if(!hittxt && !destroyed) {
  594.         if(thrown)
  595.             /* thrown => obj exists */
  596.             hit(xname(obj), mon, exclam(tmp) );
  597.         else if(Blind || !flags.verbose) You("hit it.");
  598.         else    You("hit %s%s", mon_nam(mon), exclam(tmp));
  599.     }
  600.  
  601.     if (silvermsg) {
  602.         if (cansee(mon->mx, mon->my))
  603.             pline("The silver arrow sears %s's flesh!",
  604.                 mon_nam(mon));
  605.         else
  606.             pline("Its flesh is seared!");
  607.     }
  608.  
  609.     if (needpoismsg)
  610.         kludge("The poison doesn't seem to affect %s.", mon_nam(mon));
  611.     if (poiskilled) {
  612.         pline("The poison was deadly...");
  613.         xkilled(mon, 0);
  614.         nohandglow(mon);
  615.         return FALSE;
  616.     } else if (destroyed) {
  617.         killed(mon);    /* takes care of most messages */
  618.         nohandglow(mon);
  619.     } else if(u.umconf && !thrown) {
  620.         nohandglow(mon);
  621.         if(!resist(mon, '+', 0, NOTELL)) mon->mconf = 1;
  622.         if(!mon->mstun && mon->mcanmove && !mon->msleep &&
  623.            !Blind && mon->mconf)
  624.             pline("%s appears confused.", Monnam(mon));
  625.     }
  626.  
  627. #if 0
  628.     if(mdat == &mons[PM_RUST_MONSTER] && obj && obj == uwep &&
  629.         objects[obj->otyp].oc_material == METAL &&
  630.         obj->olet == WEAPON_SYM && obj->spe > -2) {
  631.         if(obj->rustfree) {
  632.         pline("The rust on your %s vanishes instantly!",
  633.               is_sword(obj) ? "sword" : "weapon");
  634.         } else if(obj->blessed && !rnl(4))
  635.         pline("Somehow your %s is not affected!",
  636.               is_sword(obj) ? "sword" : "weapon");
  637.         else {
  638.         Your("%s!", aobjnam(obj, "corrode"));
  639.         obj->spe--;
  640.         }
  641.     }
  642. #endif
  643.  
  644.     return(destroyed ? FALSE : TRUE);
  645. }
  646.  
  647. #ifdef POLYSELF
  648.  
  649. int
  650. damageum(mdef, mattk)
  651. register struct monst *mdef;
  652. register struct attack *mattk;
  653. {
  654.     register struct permonst *pd = mdef->data;
  655.     register int    tmp = d((int)mattk->damn, (int)mattk->damd);
  656.  
  657.     stoned = FALSE;
  658.     if (is_demon(uasmon) && !rn2(13) && !uwep
  659. # ifdef INFERNO
  660.         && u.umonnum != PM_SUCCUBUS && u.umonnum != PM_INCUBUS
  661.         && u.umonnum != PM_BALROG
  662. # endif
  663.         ) {
  664.         struct monst *dtmp;
  665.         pline("Some hell-p has arrived!");
  666.         if((dtmp = makemon(!rn2(6) ? &mons[ndemon()] : uasmon, u.ux, u.uy)))
  667.         (void)tamedog(dtmp, (struct obj *)0);
  668.         return(0);
  669.     }
  670.  
  671.     switch(mattk->adtyp) {
  672.         case AD_STUN:
  673.         if(!Blind)
  674.             pline("%s staggers for a moment.", Monnam(mdef));
  675.         mdef->mstun = 1;
  676.         /* fall through to next case */
  677.         case AD_WERE:        /* no effect on monsters */
  678.         case AD_HEAL:
  679.         case AD_LEGS:
  680.         case AD_PHYS:
  681.         if(mattk->aatyp == AT_WEAP) {
  682.             if(uwep) tmp = 0;
  683.         } else if(mattk->aatyp == AT_KICK)
  684.             if(thick_skinned(mdef->data)) tmp = 0;
  685.         break;
  686.         case AD_FIRE:
  687.         if(!Blind) pline("%s is on fire!", Monnam(mdef));
  688.         tmp += destroy_mitem(mdef, SCROLL_SYM, AD_FIRE);
  689. # ifdef SPELLS
  690.         tmp += destroy_mitem(mdef, SPBOOK_SYM, AD_FIRE);
  691. # endif
  692.         if(resists_fire(pd)) {
  693.             if (!Blind)
  694.             pline("The fire doesn't heat %s!", mon_nam(mdef));
  695. # ifdef GOLEMS
  696.             golemeffects(mdef, AD_FIRE, tmp);
  697. # endif /* GOLEMS */
  698.             shieldeff(mdef->mx, mdef->my);
  699.             tmp = 0;
  700.         }
  701.         /* only potions damage resistant players in destroy_item */
  702.         tmp += destroy_mitem(mdef, POTION_SYM, AD_FIRE);
  703.         break;
  704.         case AD_COLD:
  705.         if(!Blind) pline("%s is covered in frost!", Monnam(mdef));
  706.         if(resists_cold(pd)) {
  707.             shieldeff(mdef->mx, mdef->my);
  708.             if (!Blind)
  709.             pline("The frost doesn't chill %s!", mon_nam(mdef));
  710. # ifdef GOLEMS
  711.             golemeffects(mdef, AD_COLD, tmp);
  712. # endif /* GOLEMS */
  713.             tmp = 0;
  714.         }
  715.         tmp += destroy_mitem(mdef, POTION_SYM, AD_COLD);
  716.         break;
  717.         case AD_ELEC:
  718.         if (!Blind) pline("%s is zapped!", Monnam(mdef));
  719.         tmp += destroy_mitem(mdef, WAND_SYM, AD_ELEC);
  720.         if(resists_elec(pd)) {
  721.             if (!Blind)
  722.             pline("The zap doesn't shock %s!", mon_nam(mdef));
  723. # ifdef GOLEMS
  724.             golemeffects(mdef, AD_ELEC, tmp);
  725. # endif /* GOLEMS */
  726.             shieldeff(mdef->mx, mdef->my);
  727.             tmp = 0;
  728.         }
  729.         /* only rings damage resistant players in destroy_item */
  730.         tmp += destroy_mitem(mdef, RING_SYM, AD_ELEC);
  731.         break;
  732.         case AD_ACID:
  733.         if(resists_acid(pd)) tmp = 0;
  734.         break;
  735.         case AD_STON:
  736.         if(!resists_ston(pd)) {
  737.             stoned = TRUE;
  738.             if(!Blind) pline("%s turns to stone.", Monnam(mdef));
  739.             xkilled(mdef, 0);
  740.             return(2);
  741.         }
  742.         tmp = 0;    /* no damage if this fails */
  743.         break;
  744. # ifdef SEDUCE
  745.         case AD_SSEX:
  746. # endif
  747.         case AD_SEDU:
  748.         case AD_SITM:
  749.         if(mdef->minvent) {
  750.             struct obj *otmp, *addinv(), *stealoid;
  751.  
  752.             stealoid = (struct obj *)0;
  753.             if(is_mercenary(pd) && could_seduce(&youmonst,mdef,mattk)){
  754.             for(otmp = mdef->minvent; otmp; otmp=otmp->nobj)
  755.                 if (otmp->otyp >= PLATE_MAIL && otmp->otyp
  756.                 <= ELVEN_CLOAK) stealoid = otmp;
  757.             }
  758.             if (stealoid) {
  759.             boolean stolen = FALSE;
  760.             /* Is "he"/"his" always correct? */
  761.      kludge("You seduce %s and he starts to take off his clothes.",
  762.                 mon_nam(mdef));
  763.             while(mdef->minvent) {
  764.                 otmp = mdef->minvent;
  765.                 mdef->minvent = otmp->nobj;
  766.                 /* set dknown to insure proper merge */
  767.                 if (!Blind) otmp->dknown = 1;
  768.                 if (!stolen && otmp==stealoid) {
  769.                     otmp = addinv(otmp);
  770.                     if(inv_cnt() > 52)
  771.                         dropx(otmp);
  772.                     stealoid = otmp;
  773.                     stolen = TRUE;
  774.                 } else {
  775.                     otmp = addinv(otmp);
  776.                     if(inv_cnt() > 52) {
  777.                         dropx(otmp);
  778.                         You("steal %s.", doname(otmp));
  779.                     } else {
  780.                         You("steal: ");
  781.                         prinv(otmp);
  782.                     }
  783.                 }
  784.             }
  785.             if (!stolen)
  786.                 impossible("Player steal fails!");
  787.             else {
  788.                 kludge("%s finishes taking off his suit.",
  789.                             Monnam(mdef));
  790.                 You("steal %s!", doname(stealoid));
  791. # ifdef ARMY
  792.                 mdef->data = &mons[PM_UNARMORED_SOLDIER];
  793. # endif
  794.             }
  795.            } else {
  796.             otmp = mdef->minvent;
  797.             mdef->minvent = otmp->nobj;
  798.             if (!Blind) otmp->dknown = 1;
  799.             otmp = addinv(otmp);
  800.             if(inv_cnt() > 52) {
  801.                 dropx(otmp);
  802.                 You("steal %s.", doname(otmp));
  803.             } else {
  804.                 You("steal: ");
  805.                 prinv(otmp);
  806.             }
  807.            }
  808.         }
  809.         tmp = 0;
  810.         break;
  811.         case AD_SGLD:
  812.         if (mdef->mgold) {
  813.             u.ugold += mdef->mgold;
  814.             mdef->mgold = 0;
  815.             Your("purse feels heavier.");
  816.         }
  817.         tmp = 0;
  818.         break;
  819.         case AD_TLPT:
  820.         if(tmp <= 0) tmp = 1;
  821.         if(tmp < mdef->mhp) {
  822.             rloc(mdef);
  823.             if(!Blind) pline("%s suddenly disappears!", Monnam(mdef));
  824.         }
  825.         break;
  826.         case AD_BLND:
  827.         if(haseyes(pd)) {
  828.  
  829.             if(!Blind) pline("%s is blinded.", Monnam(mdef));
  830.             mdef->mcansee = 0;
  831.             mdef->mblinded += tmp;
  832.         }
  833.         tmp = 0;
  834.         break;
  835.         case AD_CURS:
  836.         if (night() && !rn2(10) && !mdef->mcan) {
  837. # ifdef GOLEMS
  838.             if (mdef->data == &mons[PM_CLAY_GOLEM]) {
  839.             if (!Blind)
  840.                 pline("Some writing vanishes from %s's head!",
  841.                 mon_nam(mdef));
  842.             xkilled(mdef, 0);
  843.             return 2;
  844.               }
  845. # endif /* GOLEMS */
  846.             mdef->mcan = 1;
  847.             You("chuckle.");
  848.         }
  849.         tmp = 0;
  850.         break;
  851.         case AD_DRLI:
  852.         if(rn2(2) && !resists_drli(pd)) {
  853.             int xtmp = d(2,6);
  854.             kludge("%s suddenly seems weaker!", Monnam(mdef));
  855.             mdef->mhpmax -= xtmp;
  856.             if ((mdef->mhp -= xtmp) <= 0 || !mdef->m_lev--) {
  857.                 kludge("%s dies!", Monnam(mdef));
  858.                 xkilled(mdef,0);
  859.                 return(2);
  860.             }
  861.         }
  862.         tmp = 0;
  863.         break;
  864.         case AD_RUST:
  865. # ifdef GOLEMS
  866.         if (pd == &mons[PM_IRON_GOLEM]) {
  867.             kludge("%s falls to pieces!", Monnam(mdef));
  868.             xkilled(mdef,0);
  869.             return(2);
  870.         }
  871. # endif /* GOLEMS */
  872.         tmp = 0;
  873.         break;
  874.         case AD_DCAY:
  875. # ifdef GOLEMS
  876.         if (pd == &mons[PM_WOOD_GOLEM] ||
  877.             pd == &mons[PM_LEATHER_GOLEM]) {
  878.             kludge("%s falls to pieces!", Monnam(mdef));
  879.             xkilled(mdef,0);
  880.             return(2);
  881.         }
  882. # endif /* GOLEMS */
  883.         case AD_DRST:
  884.         case AD_DRDX:
  885.         case AD_DRCO:
  886.         if (!rn2(8)) {
  887.             Your("%s was poisoned!", mattk->aatyp==AT_BITE ?
  888.             "bite" : "sting");
  889.             if (resists_poison(mdef->data))
  890.             kludge("The poison doesn't seem to affect %s.",
  891.                 mon_nam(mdef));
  892.             else {
  893.             if (!rn2(10)) {
  894.                 Your("poison was deadly...");
  895.                 tmp = mdef->mhp;
  896.             } else tmp += rn1(10,6);
  897.             }
  898.         }
  899.         break;
  900.         case AD_WRAP:
  901.         case AD_STCK:
  902.         if (!sticks(mdef->data))
  903.             u.ustuck = mdef; /* it's now stuck to you */
  904.         break;
  905.         case AD_PLYS:
  906.         if (mdef->mcanmove && !rn2(3) && tmp < mdef->mhp) {
  907.             if (!Blind) pline("%s is frozen by you!", Monnam(mdef));
  908.             mdef->mcanmove = 0;
  909.             mdef->mfrozen = rnd(10);
  910.         }
  911.         break;
  912.         case AD_SLEE:
  913.         if (!resists_sleep(mdef->data) && !mdef->msleep &&
  914.                             mdef->mcanmove) {
  915.             if (!Blind)
  916.             pline("%s suddenly falls asleep!", Monnam(mdef));
  917.             mdef->mcanmove = 0;
  918.             mdef->mfrozen = rnd(10);
  919.         }
  920.         break;
  921.         default:    tmp = 0;
  922.             break;
  923.     }
  924.     if(!tmp) return(1);
  925.  
  926.     if((mdef->mhp -= tmp) < 1) {
  927.  
  928.         if(mdef->mtame) {
  929.         if(!Blind) You("killed your %s!", lmonnam(mdef) + 4);
  930.         else    You("feel embarrassed for a moment.");
  931.         } else {
  932.         if(!Blind && flags.verbose)  pline("%s is killed!", Monnam(mdef));
  933.         else        You("kill it!");
  934.         }
  935.         xkilled(mdef, 0);
  936.         return(2);
  937.     }
  938.     return(1);
  939. }
  940.  
  941. static int
  942. explum(mdef, mattk)
  943. register struct monst *mdef;
  944. register struct attack *mattk;
  945. {
  946.     switch(mattk->adtyp) {
  947.         case AD_BLND:
  948.         if(mdef->data->mlet != S_YLIGHT) {
  949.             kludge("%s is blinded by your flash of light!", Monnam(mdef));
  950.             if (mdef->mcansee) {
  951.             mdef->mblinded += rn2(25);
  952.             mdef->mcansee = 0;
  953.             }
  954.         }
  955.         break;
  956.         case AD_COLD:
  957.         You("explode!");
  958.         if (!resists_cold(mdef->data)) {
  959.             kludge("%s gets blasted!", Monnam(mdef));
  960.             mdef->mhp -= d(6,6);
  961.             if (mdef->mhp <= 0) {
  962.              killed(mdef);
  963.              return(2);
  964.             }
  965. # ifdef GOLEMS
  966.         } else if (is_golem(mdef->data)) {
  967.             golemeffects(mdef, AD_COLD, d(6,6));
  968.             shieldeff(mdef->mx, mdef->my);
  969. # endif /* GOLEMS */
  970.         } else {
  971.             shieldeff(mdef->mx, mdef->my);
  972.             kludge("The blast doesn't seem to affect %s.",
  973.                mon_nam(mdef));
  974.         }
  975.         break;
  976.         default:    break;
  977.     }
  978.     return(1);
  979. }
  980.  
  981. static int
  982. gulpum(mdef,mattk)
  983. register struct monst *mdef;
  984. register struct attack *mattk;
  985. {
  986.     register int tmp;
  987.     register int dam = d((int)mattk->damn, (int)mattk->damd);
  988.     /* Not totally the same as for real monsters.  Specifically, these
  989.      * don't take multiple moves.  (It's just too hard, for too little
  990.      * result, to program monsters which attack from inside you, which
  991.      * would be necessary if done accurately.)  Instead, we arbitrarily
  992.      * kill the monster immediately for AD_DGST and we regurgitate them
  993.      * after exactly 1 round of attack otherwise.  -KAA
  994.      */
  995.  
  996.     if(mdef->data->msize >= MZ_HUGE) return 0;
  997.  
  998.     if(u.uhunger < 1500 && !u.uswallow) {
  999.  
  1000.         if(mdef->data->mlet != S_COCKATRICE) {
  1001. # ifdef LINT    /* static char msgbuf[BUFSZ]; */
  1002.         char msgbuf[BUFSZ];
  1003. # else
  1004.         static char msgbuf[BUFSZ];
  1005. # endif
  1006. /* TODO: get the symbol display also to work (monster symbol is removed from
  1007.  * the screen and you moved onto it, then you get moved back and it gets
  1008.  * moved back if the monster survives--just like when monsters swallow you.
  1009.  */
  1010.         kludge("You engulf %s!", mon_nam(mdef));
  1011.         switch(mattk->adtyp) {
  1012.             case AD_DGST:
  1013.             u.uhunger += mdef->data->cnutrit;
  1014.             newuhs(FALSE);
  1015.             xkilled(mdef,2);
  1016.             Sprintf(msgbuf, "You totally digest %s.",
  1017.                     Blind ? "it" : mon_nam(mdef));
  1018.             if (tmp = 3 + (mdef->data->cwt >> 2)) {
  1019.                 kludge("You digest %s.", mon_nam(mdef));
  1020.                 nomul(-tmp);
  1021.                 nomovemsg = msgbuf;
  1022.             } else pline(msgbuf);
  1023.             return(2);
  1024.             case AD_PHYS:
  1025.             kludge("%s is pummeled with your debris!",Monnam(mdef));
  1026.             break;
  1027.             case AD_ACID:
  1028.             kludge("%s is covered with your goo!", Monnam(mdef));
  1029.             if (resists_acid(mdef->data)) {
  1030.                 kludge("It seems harmless to %s.", mon_nam(mdef));
  1031.                 dam = 0;
  1032.             }
  1033.             break;
  1034.             case AD_BLND:
  1035.             if (mdef->mcansee)
  1036.                 kludge("%s can't see in there!", Monnam(mdef));
  1037.             mdef->mcansee = 0;
  1038.             dam += mdef->mblinded;
  1039.             if (dam > 127) dam = 127;
  1040.             mdef->mblinded = dam;
  1041.             dam = 0;
  1042.             break;
  1043.             case AD_ELEC:
  1044.             if (rn2(2)) {
  1045.                 kludge("The air around %s crackles with electricity.", mon_nam(mdef));
  1046.                 if (resists_elec(mdef->data)) {
  1047.                 kludge("%s seems unhurt.", Monnam(mdef));
  1048.                 dam = 0;
  1049.                 }
  1050. # ifdef GOLEMS
  1051.                 golemeffects(mdef,(int)mattk->adtyp,dam);
  1052. # endif
  1053.             } else dam = 0;
  1054.             break;
  1055.             case AD_COLD:
  1056.             if (rn2(2)) {
  1057.                 if (resists_cold(mdef->data)) {
  1058.                 kludge("%s seems mildly chilly.", Monnam(mdef));
  1059.                 dam = 0;
  1060.                 } else
  1061.                 kludge("%s is freezing to death!",Monnam(mdef));
  1062. # ifdef GOLEMS
  1063.                 golemeffects(mdef,(int)mattk->adtyp,dam);
  1064. # endif
  1065.             } else dam = 0;
  1066.             break;
  1067.             case AD_FIRE:
  1068.             if (rn2(2)) {
  1069.                 if (resists_fire(mdef->data)) {
  1070.                 kludge("%s seems mildly hot.", Monnam(mdef));
  1071.                 dam = 0;
  1072.                 } else
  1073.                 kludge("%s is burning to a crisp!",Monnam(mdef));
  1074. # ifdef GOLEMS
  1075.                 golemeffects(mdef,(int)mattk->adtyp,dam);
  1076. # endif
  1077.             } else dam = 0;
  1078.             break;
  1079.         }
  1080.         if ((mdef->mhp -= dam) <= 0) {
  1081.             kludge("%s is killed!", Monnam(mdef));
  1082.             xkilled(mdef,0);
  1083.             return(2);
  1084.         }
  1085.         kludge("You %s %s!", is_animal(uasmon) ? "regurgitate"
  1086.             : "expel", mon_nam(mdef));
  1087.         if (is_animal(uasmon)) {
  1088.             if (Blind)
  1089.             pline("Obviously, you didn't like its taste.");
  1090.             else
  1091.             pline("Obviously, you didn't like %s's taste.",
  1092.                                 mon_nam(mdef));
  1093.         }
  1094.         } else {
  1095.         kludge("You bite into %s", mon_nam(mdef));
  1096.         You("turn to stone...");
  1097.         killer_format = KILLED_BY;
  1098.         killer = "swallowing a cockatrice whole";
  1099.         done(STONING);
  1100.         }
  1101.     }
  1102.     return(0);
  1103. }
  1104.  
  1105. void
  1106. missum(mdef,mattk)
  1107. register struct monst *mdef;
  1108. register struct attack *mattk;
  1109. {
  1110.     if (could_seduce(&youmonst, mdef, mattk))
  1111.         kludge("You pretend to be friendly to %s.", mon_nam(mdef));
  1112.     else if(!Blind && flags.verbose)
  1113.         You("miss %s.", mon_nam(mdef));
  1114.     else
  1115.         You("miss it.");
  1116.     wakeup(mdef);
  1117. }
  1118.  
  1119. static boolean
  1120. hmonas(mon, tmp)        /* attack monster as a monster. */
  1121. register struct monst *mon;
  1122. register int tmp;
  1123. {
  1124.     register struct attack *mattk;
  1125.     int    i, sum[NATTK];
  1126.     int    nsum = 0;
  1127.     schar    dhit;
  1128.  
  1129.     for(i = 0; i < NATTK; i++) {
  1130.  
  1131.         sum[i] = 0;
  1132.         mattk = &(uasmon->mattk[i]);
  1133.         switch(mattk->aatyp) {
  1134.         case AT_WEAP:
  1135. use_weapon:
  1136.     /* Certain monsters don't use weapons when encountered as enemies,
  1137.      * but players who polymorph into them have hands or claws and thus
  1138.      * should be able to use weapons.  This shouldn't prohibit the use
  1139.      * of most special abilities, either.
  1140.      */
  1141.     /* Potential problem: if the monster gets multiple weapon attacks,
  1142.      * we currently allow the player to get each of these as a weapon
  1143.      * attack.  Is this really desirable?
  1144.      */
  1145.             if(uwep) tmp += hitval(uwep, mon->data);
  1146.             dhit = (tmp > rnd(20) || u.uswallow);
  1147.             /* Enemy dead, before any special abilities used */
  1148.             if (!known_hitum(mon,dhit)) return 0;
  1149.             /* Do not print "You hit" message, since known_hitum
  1150.              * already did it.
  1151.              */
  1152.             if (dhit && mattk->adtyp != AD_SPEL
  1153.                 && mattk->adtyp != AD_PHYS)
  1154.                 sum[i] = damageum(mon,mattk);
  1155.             break;
  1156.         case AT_CLAW:
  1157.             if (i==0 && uwep && !cantwield(uasmon)) goto use_weapon;
  1158. # ifdef SEDUCE
  1159.             /* succubi/incubi are humanoid, but their _second_
  1160.              * attack is AT_CLAW, not their first...
  1161.              */
  1162.             if (i==1 && uwep && (u.umonnum == PM_SUCCUBUS ||
  1163.                 u.umonnum == PM_INCUBUS)) goto use_weapon;
  1164. # endif
  1165.         case AT_KICK:
  1166.         case AT_BITE:
  1167.         case AT_STNG:
  1168.         case AT_TUCH:
  1169.         case AT_BUTT:
  1170.             if (i==0 && uwep && (u.usym==S_LICH)) goto use_weapon;
  1171.             if(dhit = (tmp > rnd(20) || u.uswallow)) {
  1172.                 int compat;
  1173.  
  1174.                 if (!u.uswallow &&
  1175.                     (compat = could_seduce(&youmonst,
  1176.                                 mon, mattk)))
  1177.                 You("%s %s %s.",
  1178.                     mon->mcansee ? "smile at" : "talk to",
  1179.                     Blind ? "it" : mon_nam(mon),
  1180.                     compat == 2 ? "engagingly" : "seductively");
  1181.                 else if (mattk->aatyp == AT_KICK)
  1182.                     kludge("You kick %s.", mon_nam(mon));
  1183.                 else if (mattk->aatyp == AT_BITE)
  1184.                     kludge("You bite %s.", mon_nam(mon));
  1185.                 else if (mattk->aatyp == AT_STNG)
  1186.                     kludge("You sting %s.", mon_nam(mon));
  1187.                 else if (mattk->aatyp == AT_BUTT)
  1188.                     kludge("You butt %s.", mon_nam(mon));
  1189.                 else if (mattk->aatyp == AT_TUCH)
  1190.                     kludge("You touch %s.", mon_nam(mon));
  1191.                 else kludge("You hit %s.", mon_nam(mon));
  1192.                 sum[i] = damageum(mon, mattk);
  1193.             } else
  1194.                 missum(mon, mattk);
  1195.             break;
  1196.  
  1197.         case AT_HUGS:
  1198.             /* automatic if prev two attacks succeed, or if
  1199.              * already grabbed in a previous attack
  1200.              */
  1201.             dhit = 1;
  1202.             if (!sticks(mon->data))
  1203.                 if (mon==u.ustuck) {
  1204.                 kludge("%s is being %s.", Monnam(mon),
  1205. # ifdef GOLEMS
  1206.                     u.umonnum==PM_ROPE_GOLEM ? "choked":
  1207. # endif
  1208.                     "crushed");
  1209.                 sum[i] = damageum(mon, mattk);
  1210.                 } else if(sum[i-1] && sum[i-2]) {
  1211.                 kludge("You grab %s!", mon_nam(mon));
  1212.                 u.ustuck = mon;
  1213.                 sum[i] = damageum(mon, mattk);
  1214.                 }
  1215.             break;
  1216.  
  1217.         case AT_EXPL:    /* automatic hit if next to */
  1218.             dhit = -1;
  1219.             sum[i] = explum(mon, mattk);
  1220.             break;
  1221.  
  1222.         case AT_ENGL:
  1223.             if((dhit = (tmp > rnd(20+i))))
  1224.                 sum[i]= gulpum(mon,mattk);
  1225.             else
  1226.                 missum(mon, mattk);
  1227.             break;
  1228.  
  1229.         case AT_MAGC:
  1230.             /* No check for uwep; if wielding nothing we want to
  1231.              * do the normal 1-2 points bare hand damage...
  1232.              */
  1233.             if (i==0 && (u.usym==S_KOBOLD
  1234.                 || u.usym==S_ORC
  1235.                 || u.usym==S_GNOME
  1236.                 )) goto use_weapon;
  1237.  
  1238.         case AT_NONE:
  1239.             continue;
  1240.             /* Not break--avoid passive attacks from enemy */
  1241.  
  1242.         default: /* Strange... */
  1243.             impossible("strange attack of yours (%d)",
  1244.                  mattk->aatyp);
  1245.         case AT_BREA:
  1246.         case AT_SPIT:
  1247.         case AT_GAZE:    /* all done using #monster command */
  1248.             dhit = 0;
  1249.             break;
  1250.         }
  1251.         if (dhit == -1)
  1252.         rehumanize();
  1253.         if(sum[i] == 2) return(passive(mon, 1, 0, (mattk->aatyp==AT_KICK)));
  1254.                             /* defender dead */
  1255.         else {
  1256.         (void) passive(mon, sum[i], 1, (mattk->aatyp==AT_KICK));
  1257.         nsum |= sum[i];
  1258.         }
  1259.         if (uasmon == &playermon)
  1260.         break; /* No extra attacks if no longer a monster */
  1261.         if (multi < 0)
  1262.         break; /* If paralyzed while attacking, i.e. floating eye */
  1263.     }
  1264.     return(nsum);
  1265. }
  1266.  
  1267. #endif /* POLYSELF */
  1268.  
  1269. /*    Special (passive) attacks on you by monsters done here.        */
  1270.  
  1271. int
  1272. passive(mon, mhit, malive, kicked)
  1273. register struct monst *mon;
  1274. register boolean mhit;
  1275. register int malive;
  1276. boolean kicked;
  1277. {
  1278.     register struct permonst *ptr = mon->data;
  1279.     register int i, tmp;
  1280.  
  1281.     for(i = 0; ; i++) {
  1282.         if(i >= NATTK) return(malive | mhit);    /* no passive attacks */
  1283.         if(ptr->mattk[i].aatyp == AT_NONE) break;    /* try this one */
  1284.     }
  1285.  
  1286. /*    These affect you even if they just died */
  1287.  
  1288.     switch(ptr->mattk[i].adtyp) {
  1289.  
  1290.       case AD_ACID:
  1291.         if(mhit && rn2(2)) {
  1292.         if (Blind || !flags.verbose) You("are splashed!");
  1293.         else    You("are splashed by %s's acid!", mon_nam(mon));
  1294.  
  1295.         tmp = d((int)mon->m_lev, (int)ptr->mattk[i].damd);
  1296. #ifdef POLYSELF
  1297.         if(!resists_acid(uasmon))
  1298. #endif
  1299.             mdamageu(mon, tmp);
  1300.         if(!rn2(30)) corrode_armor();
  1301.         }
  1302.         if(mhit && !rn2(6)) {
  1303.         if (kicked) {
  1304.             if (uarmf)
  1305.             (void) rust_dmg(uarmf, xname(uarmf), 3, TRUE);
  1306.         } else corrode_weapon();
  1307.         }
  1308.         break;
  1309.       case AD_STON:
  1310.         if(mhit)
  1311.           if (!kicked)
  1312.         if (!uwep && !uarmg
  1313. #ifdef POLYSELF
  1314.             && !resists_ston(uasmon)
  1315. #endif
  1316.            ) {
  1317.             You("turn to stone...");
  1318.             done_in_by(mon);
  1319.             return 2;
  1320.         }
  1321.         break;
  1322.       case AD_RUST:
  1323.         if(mhit)
  1324.           if (kicked) {
  1325.         if (uarmf)
  1326.             (void) rust_dmg(uarmf, xname(uarmf), 1, TRUE);
  1327.           } else
  1328.         corrode_weapon();
  1329.         break;
  1330.       case AD_MAGM:
  1331.         /* wrath of gods for attacking Oracle */
  1332.         if(Antimagic) {
  1333.         shieldeff(u.ux, u.uy);
  1334.         pline("A hail of magic missiles narrowly misses you!");
  1335.         } else {
  1336.         tmp = d((int)mon->m_lev+1, (int)ptr->mattk[i].damd);
  1337.         You("are hit by magic missiles appearing from thin air!");
  1338.         mdamageu(mon, tmp);
  1339.         }
  1340.         break;
  1341.       default:
  1342.         break;
  1343.     }
  1344.  
  1345. /*    These only affect you if they still live */
  1346.  
  1347.     if(malive && !mon->mcan && rn2(3)) {
  1348.  
  1349.         switch(ptr->mattk[i].adtyp) {
  1350.  
  1351.           case AD_PLYS:
  1352.         tmp = -d((int)mon->m_lev+1, (int)ptr->mattk[i].damd);
  1353.         if(ptr == &mons[PM_FLOATING_EYE]) {
  1354.             if (!canseemon(mon)) {
  1355.             tmp = 0;
  1356.             break;
  1357.             }
  1358.             if(mon->mcansee) {
  1359.             if(Reflecting & W_AMUL) {
  1360.                 makeknown(AMULET_OF_REFLECTION);
  1361.                 pline("%s's gaze is reflected by your medallion.",
  1362.                   Monnam(mon));
  1363.             } else if(Reflecting & W_ARMS) {
  1364.                 makeknown(SHIELD_OF_REFLECTION);
  1365.                 pline("%s's gaze is reflected by your shield.",
  1366.                   Monnam(mon));
  1367.             } else {
  1368.                 You("are frozen by %s's gaze!", mon_nam(mon));
  1369.                 nomul((ACURR(A_WIS) > 12 || rn2(4)) ? tmp : -120);
  1370.             }
  1371.             } else {
  1372.             pline("%s cannot defend itself.", Amonnam(mon,"blind"));
  1373.             if(!rn2(500)) change_luck(-1);
  1374.             }
  1375.         } else { /* gelatinous cube */
  1376.             You("are frozen by %s!", mon_nam(mon));
  1377.             nomul(tmp);
  1378.             tmp = 0;
  1379.         }
  1380.         break;
  1381.           case AD_COLD:        /* brown mold or blue jelly */
  1382.         if(monnear(mon, u.ux, u.uy)) {
  1383.             tmp = d((int)mon->m_lev+1, (int)ptr->mattk[i].damd);
  1384.             if(Cold_resistance) {
  1385.               shieldeff(u.ux, u.uy);
  1386.             You("feel a mild chill.");
  1387. #ifdef POLYSELF
  1388. #ifdef GOLEMS
  1389.             ugolemeffects(AD_COLD, tmp);
  1390. #endif /* GOLEMS */
  1391. #endif
  1392.             tmp = 0;
  1393.             break;
  1394.             }
  1395.             You("are suddenly very cold!");
  1396.             mdamageu(mon, tmp);
  1397.         /* monster gets stronger with your heat! */
  1398.             mon->mhp += tmp / 2;
  1399.             if (mon->mhpmax < mon->mhp) mon->mhpmax = mon->mhp;
  1400.         /* at a certain point, the monster will reproduce! */
  1401.             if(mon->mhpmax > ((mon->m_lev+1) * 8)) {
  1402.             register struct monst *mtmp;
  1403.  
  1404.             if(mtmp = clone_mon(mon)) {
  1405.                 mtmp->mhpmax = mon->mhpmax /= 2;
  1406.                 if(!Blind)
  1407.                 pline("%s multiplies from your heat!",
  1408.                                 Monnam(mon));
  1409.             }
  1410.             }
  1411.         }
  1412.         break;
  1413.           case AD_STUN:        /* specifically yellow mold */
  1414.         if(!Stunned)
  1415.             make_stunned((long)d((int)mon->m_lev+1, (int)ptr->mattk[i].damd), TRUE);
  1416.         break;
  1417.           case AD_FIRE:
  1418.         if(monnear(mon, u.ux, u.uy)) {
  1419.             tmp = d((int)mon->m_lev+1, (int)ptr->mattk[i].damd);
  1420.             if(Fire_resistance) {
  1421.             shieldeff(u.ux, u.uy);
  1422.             You("feel mildly warm.");
  1423. #if defined(POLYSELF) && defined(GOLEMS)
  1424.             ugolemeffects(AD_FIRE, tmp);
  1425. #endif
  1426.             tmp = 0;
  1427.             break;
  1428.             }
  1429.             You("are suddenly very hot!");
  1430.             mdamageu(mon, tmp);
  1431.         }
  1432.         break;
  1433.           case AD_ELEC:
  1434.         tmp = d((int)mon->m_lev+1, (int)ptr->mattk[i].damd);
  1435.         if(Shock_resistance) {
  1436.             shieldeff(u.ux, u.uy);
  1437.             You("feel a mild tingle.");
  1438. #if defined(POLYSELF) && defined(GOLEMS)
  1439.             ugolemeffects(AD_ELEC, tmp);
  1440. #endif
  1441.             tmp = 0;
  1442.             break;
  1443.         }
  1444.         You("are jolted with electricity!");
  1445.         mdamageu(mon, tmp);
  1446.         break;
  1447.           default:
  1448.         break;
  1449.         }
  1450.     }
  1451.     return(malive | mhit);
  1452. }
  1453.  
  1454. /* Note: caller must ascertain mtmp->mimic... */
  1455. void
  1456. stumble_onto_mimic(mtmp)
  1457. register struct monst *mtmp;
  1458. {
  1459.     if(!u.ustuck && !mtmp->mflee && dmgtype(mtmp->data,AD_STCK))
  1460.         u.ustuck = mtmp;
  1461.     if (Blind) goto generic;
  1462.     else if (levl[u.ux+u.dx][u.uy+u.dy].scrsym == CLOSED_DOOR_SYM)
  1463. #ifdef SPELLS
  1464.     {
  1465.         if (IS_ROCK(levl[u.ux+u.dx][u.uy+u.dy].typ) ||
  1466.             IS_DOOR(levl[u.ux+u.dx][u.uy+u.dy].typ))
  1467. #endif
  1468.             pline("The door actually was %s.", defmonnam(mtmp));
  1469. #ifdef SPELLS
  1470.         else
  1471.             pline("That spellbook was %s.", defmonnam(mtmp));
  1472.     }
  1473. #endif
  1474.     else if (levl[u.ux+u.dx][u.uy+u.dy].scrsym == GOLD_SYM)
  1475.         pline("That gold was %s!", defmonnam(mtmp));
  1476.     else {
  1477. generic:
  1478.         pline("Wait!  That's %s!", defmonnam(mtmp));
  1479.     }
  1480.     wakeup(mtmp);    /* clears mtmp->mimic */
  1481. }
  1482.  
  1483. static void
  1484. nohandglow(mon)
  1485. struct monst *mon;
  1486. {
  1487.     if (!u.umconf || mon->mconf) return;
  1488.     if (u.umconf == 1) {
  1489.         if (Blind)
  1490.             Your("%s stop tingling.", makeplural(body_part(HAND)));
  1491.         else
  1492.             Your("%s stop glowing %s.",
  1493.                 makeplural(body_part(HAND)),
  1494.                 Hallucination ? hcolor() : red);
  1495.     } else {
  1496.         if (Blind)
  1497.             pline("The tingling in your %s lessens.",
  1498.                 makeplural(body_part(HAND)));
  1499.         else
  1500.             Your("%s no longer glow so brightly %s.",
  1501.                 makeplural(body_part(HAND)),
  1502.                 Hallucination ? hcolor() : red);
  1503.     }
  1504.     u.umconf--;
  1505. }
  1506.